package com.linxchong.security.filter;

import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.*;
import org.springframework.stereotype.Component;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;

import javax.servlet.http.HttpServletRequest;

/**
 * @Author:linchong
 * @CreateTime:2020-07-14 21:11
 * @Description:
 */
@Slf4j
@Component
public class OAuthFilter extends ZuulFilter {


	private RestTemplate restTemplate = new RestTemplate();
	/**
	 * 过滤器的类型，可以有四种(四个字符串)
	 * pre, ->业务逻辑执行之前，会执行过滤器里的逻辑
	 * post,->业务逻辑执行之后，回去执行run里面的逻辑
	 * error,->业务逻辑执行出错后，会执行run里面的逻辑
	 * route  ->控制路由，一般不手写，zuul帮助
	 *
	 * @return
	 */
	@Override
	public String filterType() {
		return "pre";
	}

	/**
	 * 控制过滤器的执行顺序，几种安全机制(认证，授权，限流等)都是有顺序的
	 * @return
	 */
	@Override
	public int filterOrder() {
		return 1;
	}

	/**
	 * 自定义逻辑，判断该过滤器是否起作用
	 *
	 * @return
	 */
	@Override
	public boolean shouldFilter() {
		return true;
	}

	/**
	 * 真正要写的业务逻辑的地方
	 * @return
	 * @throws ZuulException
	 */
	@Override
	public Object run() throws ZuulException {
		log.info("[oauth start...]");
		//帮助获取请求响应对象
		RequestContext requestContext = RequestContext.getCurrentContext();
		//获取当前请求对象
		HttpServletRequest request = requestContext.getRequest();
		//判断请求的地址，执行不同的操作
		if(StringUtils.startsWith(request.getRequestURI(),"/token")){
			//认证的请求，直接放行
			return null;
		}
		String authHeader = request.getHeader("Authorization");
		//请求头为空
		if(StringUtils.isBlank(authHeader)){
			log.debug("请求头为空-1...");
			return null;
		}
		authHeader = authHeader.toLowerCase();
		log.info("token is:{}",authHeader);
		if(!StringUtils.startsWithIgnoreCase(authHeader,"bearer ")){
			log.debug("请求头为空-2...");
			return null;
		}
		try{
			//获取令牌的信息,即调用认证服务信息的返回
			TokenInfo info = getTokenInfo(authHeader);
			request.setAttribute("tokenInfo",info);
		}catch (Exception e){
			log.error("get token info fail ...",e);
		}

		return null;
	}

	private TokenInfo getTokenInfo(String authHeader) {

		String token = StringUtils.substringAfter(authHeader,"bearer ");
		String oauthServiceUrl = "http://localhost:9090/oauth/check_token";
		HttpHeaders headers = new HttpHeaders();
		//请求内容格式
		headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
		//请求信息,网关的clientid和clientSecret
		headers.setBasicAuth("gateway","123456");
		//填充请求参数
		//注意这里只能用它
		MultiValueMap<String,String> params = new LinkedMultiValueMap<>();
		params.add("token",token);
		HttpEntity<MultiValueMap<String,String>> entity = new HttpEntity<>(params,headers);
		//发送请求
		ResponseEntity<TokenInfo> response =  restTemplate.exchange(oauthServiceUrl, HttpMethod.POST,entity,TokenInfo.class);
		log.info("token info:{}",response.getBody().toString());
		log.info("oauth end...");
		return response.getBody();
	}
}
